package com.gopay.bis.icbc.expay.operation;

import java.util.List;
import java.util.Map;

import com.gopay.common.cipher.utils.LoggerMaskUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.IcbcConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.icbc.expay.IcbcExpayCmsEbPubReq;
import com.gopay.common.domain.bank.icbc.expay.pay.req.IcbcExpayCmsEbReq;
import com.gopay.common.domain.bank.icbc.expay.pay.req.IcbcExpayCmsReq;
import com.gopay.common.domain.bank.icbc.expay.pay.res.IcbcExpayCmsRes;
import com.gopay.common.domain.bank.icbc.expay.prepay.req.IcbcPreExpayCmsEbReq;
import com.gopay.common.domain.bank.icbc.expay.prepay.req.IcbcPreExpayCmsReq;
import com.gopay.common.domain.bank.icbc.expay.prepay.res.IcbcPreExpayCmsRes;
import com.gopay.common.domain.bank.icbc.expay.query.req.IcbcQueryExpayCmsEbReq;
import com.gopay.common.domain.bank.icbc.expay.query.req.IcbcQueryExpayCmsReq;
import com.gopay.common.domain.bank.icbc.expay.query.res.IcbcQueryExpayCmsRes;
import com.gopay.common.exception.GopayException;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

import cn.com.infosec.util.Base64;

/** 
 * 工行快捷辅助类
 * @ClassName: IcbcExpayHelper 
 * @author w_jiqing 
 * @date 2017年6月27日 下午2:34:21  
 */ 
public class IcbcExpayHelper {
    
    private static final String EXPAY_PRE = "<?xml version=\"1.0\" encoding=\"GBK\" ?>\n";
    
    private static Log logger = LogFactory.getLog(IcbcExpayHelper.class);
    
    private final static String REQDATA = "reqData=";
    
    private String STR ="/servlet/ICBCCMPAPIReqServlet";
    private String channles;
    private List<String> urls;
    private Map<String,String> signUrls;
    private Map<String,String> ids;
    private Transformer expaytransformer;

    
    public String sendQueryOrderReq(BaseMessage baseMsg) throws GopayException{
        String res= "";
        String url ="";
        String id = "";
        for (String str : urls) {
            if(channles.startsWith(str)){
                id = ids.get(str);
                url = str+STR;
            }
        }
        try{
            logger.error("icbc expay query id:"+id+",queryUrl:"+url);
            IcbcQueryExpayCmsReq message = (IcbcQueryExpayCmsReq) baseMsg;
            IcbcQueryExpayCmsEbReq eb =message.getEb();
            IcbcExpayCmsEbPubReq pub = eb.getPub();
            pub.setId(id);
            eb.setPub(pub);
            message.setEb(eb);
            XStream xs = new XStream(new DomDriver());
            xs.autodetectAnnotations(true);
            String reqData = xs.toXML(message);
            StringBuffer sb = new StringBuffer(EXPAY_PRE);
            sb.append(reqData);
            message.setPlainMessage(sb.toString());
            logger.error("icbc expay query xml:"+sb.toString());
            Map issueNCParaMap = expaytransformer.getPacketIssueNCParaMap(pub, message.getPlainMessage().getBytes("UTF-8"));
            HttpTransport transport = new HttpTransport();
            transport.setUrl(url);
            Object issueRes = transport.submit(issueNCParaMap);
            res = new String((byte[]) issueRes);
            return res;
        }catch(GopayException e){
            if(ProcCodeConstants.PROC_CODE_100E6047.equals(e.getErrCode())){
                throw  new GopayException(ProcCodeConstants.PROC_CODE_100E6047,"批量接口连接前置机"+url);
            }else{
                throw new GopayException(ProcCodeConstants.PROC_CODE_100E6045);
            }
        }catch(Exception e){
            logger.error(" icbc bcdl  queryPacket error message: ", e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6049);
        }
    }
        
    
    public String sendPaymentReq(BaseMessage baseMsg) throws GopayException{
        String res  = "";
        String url ="";
        String signUrl="";
        String id = "";
        for (String str : urls) {
            if(channles.startsWith(str)){
                id = ids.get(str);
                signUrl=signUrls.get(str);
                url = str+STR;
            }
        }
        try{
            logger.error("icbc expay payment id:"+id+",signUrl:"+signUrl+",payUrl:"+url);
            IcbcExpayCmsReq message = (IcbcExpayCmsReq) baseMsg;
            IcbcExpayCmsEbReq eb =message.getEb();
            IcbcExpayCmsEbPubReq pub = eb.getPub();
            pub.setId(id);
            eb.setPub(pub);
            message.setEb(eb);
            XStream xs = new XStream(new DomDriver());
            xs.autodetectAnnotations(true);
            String reqData = xs.toXML(message);
            StringBuffer sb = new StringBuffer(EXPAY_PRE);
            sb.append(reqData);
            BankLogUtils.printExPaySignSendLog(message);
            logger.info(message.getOutStlmCd() + " exPay plainMessage: " + LoggerMaskUtils.maskString(sb.toString()));
            message.setPlainMessage(sb.toString());
            Map issueNCParaMap = expaytransformer.getIssueNCParaMap(pub, message.getPlainMessage().getBytes("UTF-8"),signUrl);
            HttpTransport transport = new HttpTransport();
            transport.setUrl(url);
            Object issueRes = transport.submit(issueNCParaMap);
            res = new String((byte[]) issueRes);
            logger.error("icbc expay payment return message:"+res);
        }catch(GopayException e){
            if(ProcCodeConstants.PROC_CODE_100E6047.equals(e.getErrCode())){
                throw  new GopayException(ProcCodeConstants.PROC_CODE_100E6047,"前置机地址"+url);
            }else if(ProcCodeConstants.PROC_CODE_100E6082.equals(e.getErrCode())){
                throw  new GopayException(ProcCodeConstants.PROC_CODE_100E6082,"签名失败, 前置机地址"+signUrl);
            }else{
                throw new GopayException(ProcCodeConstants.PROC_CODE_100E6045);
            }
        }catch(Exception e){
            logger.error(" icbc expay  payment error message: ", e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6045);
        }
        return res;
        
    }
    
    public String sendSendSmsReq(BaseMessage baseMsg) throws GopayException{
        String res  = "";
        String url ="";
        String signUrl="";
        String id = "";
        for (String str : urls) {
            if(channles.startsWith(str)){
                id = ids.get(str);
                signUrl=signUrls.get(str);
                url = str+STR;
            }
        }
        try{
            logger.error("icbc expay send sms id:"+id+",signUrl:"+signUrl+",payUrl:"+url);
            IcbcPreExpayCmsReq message = (IcbcPreExpayCmsReq) baseMsg;
            IcbcPreExpayCmsEbReq eb =message.getEb();
            IcbcExpayCmsEbPubReq pub = eb.getPub();
            pub.setId(id);
            eb.setPub(pub);
            message.setEb(eb);
            XStream xs = new XStream(new DomDriver());
            xs.autodetectAnnotations(true);
            String reqData = xs.toXML(message);
            StringBuffer sb = new StringBuffer(EXPAY_PRE);
            sb.append(reqData);
            BankLogUtils.printExPaySignSendLog(message);
            logger.info(message.getOutStlmCd() + " exPay plainMessage: " + LoggerMaskUtils.maskString(sb.toString()));
            message.setPlainMessage(sb.toString());
            Map issueNCParaMap = expaytransformer.getIssueNCParaMap(pub, message.getPlainMessage().getBytes("UTF-8"),signUrl);
            HttpTransport transport = new HttpTransport();
            transport.setUrl(url);
            Object issueRes = transport.submit(issueNCParaMap);
            res = new String((byte[]) issueRes);
            logger.error("icbc expay return message:"+res);
        }catch(GopayException e){
            if(ProcCodeConstants.PROC_CODE_100E6047.equals(e.getErrCode())){
                throw  new GopayException(ProcCodeConstants.PROC_CODE_100E6047,"前置机地址"+url);
            }else if(ProcCodeConstants.PROC_CODE_100E6082.equals(e.getErrCode())){
                throw  new GopayException(ProcCodeConstants.PROC_CODE_100E6082,"签名失败, 前置机地址"+signUrl);
            }else{
                throw new GopayException(ProcCodeConstants.PROC_CODE_100E6045);
            }
        }catch(Exception e){
            logger.error(" icbc expay  eft error message: ", e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6045);
        }
        return res;
    }
    
    public Object parseQuery(String responseBody) throws GopayException{
        BaseMessage baseMessage = new BaseMessage();
        baseMessage.setOutStlmCd(BankConstants.BANK_LOGO_ICBC); // 为了区分日志输出
        try{
            responseBody = responseBody.substring(REQDATA.length());
            // Base64转码
            String plainMessage = "";
            plainMessage = new String(Base64.decode(new String(responseBody.getBytes("GBK"), "UTF-8")), "GBK");
            logger.info("ICBC expay query resData：" + plainMessage);
            IcbcQueryExpayCmsRes res = new IcbcQueryExpayCmsRes();
            XStream xs = new XStream(new DomDriver());
            xs.autodetectAnnotations(true);
            xs.toXML(res);
            return xs.fromXML(plainMessage); 
        }catch (Exception e) {
            BankLogUtils.printExPayExceptionLog(baseMessage, e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6079);
        }
    }
    
    public Object parsePayment(String responseBody) throws GopayException{
        BaseMessage baseMessage = new BaseMessage();
        baseMessage.setOutStlmCd(BankConstants.BANK_LOGO_ICBC); // 为了区分日志输出
        try{
            responseBody = responseBody.substring(REQDATA.length());
            // Base64转码
            String plainMessage = "";
            plainMessage = new String(Base64.decode(new String(responseBody.getBytes("GBK"), "UTF-8")), "GBK");
            logger.info("ICBC expay payment resData：" + plainMessage);
            IcbcExpayCmsRes res = new IcbcExpayCmsRes();
            XStream xs = new XStream(new DomDriver());
            xs.autodetectAnnotations(true);
            xs.toXML(res);
            return xs.fromXML(plainMessage); 
        }catch (Exception e) {
            BankLogUtils.printExPayExceptionLog(baseMessage, e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6079);
        }
    }
    
    /**
     * 截取返回消息体并做base64转码
     * 
     * @param responseBody
     * @return String
     * 
     * */
    public Object parseSendSms(String responseBody) throws GopayException{
        BaseMessage baseMessage = new BaseMessage();
        baseMessage.setOutStlmCd(BankConstants.BANK_LOGO_ICBC); // 为了区分日志输出
        try {
            responseBody = responseBody.substring(REQDATA.length());
            // Base64转码
            String plainMessage = "";
            plainMessage = new String(Base64.decode(new String(responseBody.getBytes("GBK"), "UTF-8")), "GBK");
            logger.info("ICBC expay prePayment resData：" + LoggerMaskUtils.maskString(plainMessage));
            IcbcPreExpayCmsRes res = new IcbcPreExpayCmsRes();
            XStream xs = new XStream(new DomDriver());
            xs.autodetectAnnotations(true);
            xs.toXML(res);
            return xs.fromXML(plainMessage);             
        } catch (Exception e) {
            BankLogUtils.printExPayExceptionLog(baseMessage, e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6079);
        }
    }
    
    public String resolveResMsgBody(Object issueRes) throws GopayException {
        byte[] resByte = (byte[]) issueRes;
        String resStr = new String(resByte);
        int index = resStr.indexOf(IcbcConstants.NORMAL_RES_FIELD);
        if (index != -1) {
            String msgBody = resStr.substring(IcbcConstants.NORMAL_RES_FIELD
                    .length());
            return msgBody;
        } else {
            throw new GopayException(resStr);
        }
    }


    public String getChannles() {
        return channles;
    }

    public void setChannles(String channles) {
        this.channles = channles;
    }

    public List<String> getUrls() {
        return urls;
    }

    public void setUrls(List<String> urls) {
        this.urls = urls;
    }

    public Map<String, String> getSignUrls() {
        return signUrls;
    }

    public void setSignUrls(Map<String, String> signUrls) {
        this.signUrls = signUrls;
    }

    public Map<String, String> getIds() {
        return ids;
    }

    public void setIds(Map<String, String> ids) {
        this.ids = ids;
    }

    public Transformer getExpaytransformer() {
        return expaytransformer;
    }

    public void setExpaytransformer(Transformer expaytransformer) {
        this.expaytransformer = expaytransformer;
    }
    
    

}
